﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpMUD.Framework.Workflow.SessionState;
using SharpMUD.Framework.Net.Telnet;
using SharpMUD.Framework.Services;
using System.IO;
using SharpMUD.Framework.Services.Security;
using SharpMUD.Framework.Security;
using SharpMUD.Framework.Workflow.Generic;
using SharpMUD.Framework.IO.HumanInterface.Terminal;

namespace SharpMUD.Application.DebugHarness
{
    public static class SampleSessionStates<TSession>
        where TSession : IInteractiveTerminalSession, IHasSessionState<TSession>
    {
        public static System.Type DefaultType
        {
            get
            {
                return typeof(DefaultSessionState);
            }
        }

        public class DefaultSessionState
            : ISessionState<TSession>
        {
            public DefaultSessionState() { }

            #region ISessionState<TSession> Members

            public string ID
            {
                get { return "NewConnection"; }
            }

            public SessionActionResult PerformAction(TSession session)
            {
                session.RootSessionState.Push(Logon);
                session.RootSessionState.Push(WriteWelcomeScreen);


                session.RootSessionState.Enqueue(FreezeConnection);

                return SessionActionResult.Complete;
            }


            #endregion
        }

        private static ISessionState<TSession> FreezeConnection
        {
            get
            {
                return CreateSessionState<TSession>("FreezeConnection",
                    (s) => SessionActionResult.Incomplete);
            }
        }

        private static ISessionState<T> CreateSessionState<T>(string id, SessionAction<T> action)
            where T : IUserSession
        {
            return new RuntimeSessionState<T>(id, action);
        }

        private static ISessionState<TSession> Logon
        {
            get
            {
                return CreateSessionState<TSession>("Logon",
                    delegate(TSession s)
                    {
                        s.RootSessionState.Push(GeneratePrompt("GetUsername", "By what name are you known here? ",
                            delegate(TSession s2, string enteredUsername)
                            {
                                s2.RootSessionState.Push(CreateSessionState<TSession>("HandleEnteredUsername",
                                    delegate(TSession session)
                                    {
                                        session.Terminal.WriteLine();
                                        session.Terminal.WriteLine();
                                        session.Terminal.WriteLine("Hello there, {0}!", enteredUsername);
                                        session.Terminal.WriteLine();

                                        s2.RootSessionState.Push(CommandPromptAgent(enteredUsername));

                                        return SessionActionResult.Complete;
                                    }));
                            }));

                        return SessionActionResult.Complete;
                    });

            }
        }

        private static ISessionState<TSession> CommandPromptAgent(string username)
        {
            return CreateSessionState<TSession>("CommandPromptAgent",
                delegate(TSession s)
                {
                    if (true)
                    {
                        s.RootSessionState.Push(GeneratePrompt("CommandPrompt", String.Format("{0}@SharpMUD> ", username), GetCommandPromptInputHandler(username)));
                    }
                    return SessionActionResult.Incomplete;
                });
        }
        private static Action<TSession,string> GetCommandPromptInputHandler(string username)
        {
            return
                delegate(TSession s, string input)
                {
                    if (String.Equals(input, "shutdown", StringComparison.OrdinalIgnoreCase))
                    {
                        if ((s is TelnetSession) && (s as TelnetSession).ServiceHost is IControlledExecution)
                        {
                            s.Terminal.WriteLine("Shutting down...");
                            ((s as TelnetSession).ServiceHost as IControlledExecution).Stop();
                        }
                        else
                        {
                            s.Terminal.WriteLine("Shutdown not possible from the current context!");
                        }
                    }
                };
        }

        private static ISessionState<TSession> GeneratePrompt(string promptID, string promptText, Action<TSession, string> handlePromptResponse)
        {
            return CreateSessionState<TSession>("WritePrompt:" + promptID,
                delegate(TSession s)
                {
                    if (s is TelnetSession)
                    {
                        (s as TelnetSession).WritePrompt(promptText);
                    }
                    else
                    {
                        //Fix this... (abstraction problem)
                        s.Terminal.Write(promptText);
                    }
                    s.RootSessionState.Push(GeneratePromptResponseWaiter(promptID, handlePromptResponse));
                    return SessionActionResult.Complete;
                }
            );
        }
        private static ISessionState<TSession> GeneratePromptResponseWaiter(string promptID, Action<TSession,string> handlePromptResponse)
        {
            return CreateSessionState<TSession>("PromptWaiter:" + promptID,
                delegate(TSession s)
                {
                    string enteredText = s.Terminal.ReadLine();
                    if (enteredText == null)
                        return SessionActionResult.Incomplete;
                    else
                    {
                        handlePromptResponse(s, enteredText);
                        return SessionActionResult.Complete;
                    }
                }
            );
        }

        private static ISessionState<TSession> WriteWelcomeScreen
        {
            get
            {
                return CreateSessionState<TSession>("WriteWelcomeScreen",
                    delegate(TSession s)
                    {
                        s.Terminal.WriteLine("SharpMUD v1.0.1");
                        s.Terminal.WriteLine("(C)opyright Bruce Markham, 2003-2008; Some rights reserved.");
                        s.Terminal.WriteLine("");
                        s.Terminal.WriteLine("");
                        s.Terminal.WriteLine(GetCastleGraphic());
                        return SessionActionResult.Complete;
                    });
            }
        }

        private static string GetCastleGraphic()
        {
            using (var x = new StreamReader("Castle.txt"))
            {
                return x.ReadToEnd();
            }
        }
    }
}
